home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / disk-man / mtools-3.000 / mtools-3 / mtools-3.0 / mcopy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-08  |  8.3 KB  |  406 lines

  1. /*
  2.  * mcopy.c
  3.  * Copy an MSDOS files to and from Unix
  4.  *
  5.  */
  6.  
  7.  
  8. #define LOWERCASE
  9.  
  10. #include "sysincludes.h"
  11. #include "msdos.h"
  12. #include "mtools.h"
  13. #include "vfat.h"
  14. #include "streamcache.h"
  15. #include "plain_io.h"
  16. #include "nameclash.h"
  17. #include "file.h"
  18. #include "fs.h"
  19.  
  20. /*
  21.  * Preserve the file modification times after the fclose()
  22.  */
  23.  
  24. static void set_mtime(char *target, long mtime)
  25. {
  26. #ifdef HAVE_UTIMES
  27.     struct timeval tv[2];
  28.  
  29.     if (mtime != 0L) {
  30.         tv[0].tv_sec = mtime;
  31.         tv[0].tv_usec = 0;
  32.         tv[1].tv_sec = mtime;
  33.         tv[1].tv_usec = 0;
  34.         utimes(target, tv);
  35.     }
  36. #else
  37. #ifdef HAVE_UTIME
  38.     struct utimbuf utbuf;
  39.  
  40.     if (mtime != 0L) {
  41.         utbuf.actime = mtime;
  42.         utbuf.modtime = mtime;
  43.         utime(target, &utbuf);
  44.     }
  45. #endif
  46. #endif
  47.     return;
  48. }
  49.  
  50. typedef struct Arg_t {
  51.     int preserve;
  52.     char *target;
  53.     int textmode;
  54.     int needfilter;
  55.     int nowarn;
  56.     int single;
  57.     int interactive;
  58.     int verbose;
  59.     int type;
  60.     StreamCache_t sc;
  61.     ClashHandling_t ch;
  62.     Stream_t *sourcefile;
  63.     Stream_t *targetDir;
  64.     Stream_t *targetFs;
  65.     char *progname;
  66. } Arg_t;
  67.  
  68. static int read_file(Stream_t *Dir, StreamCache_t *sc, int entry, 
  69.              int needfilter)
  70. {
  71.     Arg_t *arg=(Arg_t *) sc->arg;
  72.     long mtime;
  73.     Stream_t *File=sc->File;
  74.     Stream_t *Target, *Source;
  75.     struct stat stbuf;
  76.     int ret;
  77.     char errmsg[80];
  78.  
  79.     File->Class->get_data(File, &mtime, 0, 0, 0);
  80.     
  81.     if (!arg->preserve)
  82.         mtime = 0L;
  83.  
  84.     /* if we are creating a file, check whether it already exists */
  85.     if (!arg->nowarn && strcmp(arg->target, "-") && 
  86.         !access(arg->target, 0)){
  87.         if( ask_confirmation("File \"%s\" exists, overwrite (y/n) ? ",
  88.                      arg->target,0))
  89.             return MISSED_ONE;
  90.         
  91.         /* sanity checking */
  92.         if (!stat(arg->target, &stbuf) && !S_ISREG(stbuf.st_mode)) {
  93.             fprintf(stderr,"\"%s\" is not a regular file\n",
  94.                 arg->target);            
  95.             return MISSED_ONE;
  96.         }
  97.     }
  98.  
  99.     if(!arg->type)
  100.         fprintf(stderr,"Copying %s\n", sc->outname);
  101.     if(got_signal)
  102.         return MISSED_ONE;
  103.     if ((Target = SimpleFloppyOpen(0, 0, arg->target,
  104.                        O_WRONLY | O_CREAT | O_TRUNC,
  105.                        errmsg))) {
  106.         ret = 0;
  107.         if(needfilter && arg->textmode){
  108.             Source = open_filter(COPY(File));
  109.             if (!Source)
  110.                 ret = -1;
  111.         } else
  112.             Source = COPY(File);
  113.  
  114.         if (ret == 0 )
  115.             ret = copyfile(Source, Target);
  116.         FREE(&Source);
  117.         FREE(&Target);
  118.         if(ret < -1){
  119.             unlink(arg->target);
  120.             return MISSED_ONE;
  121.         }
  122.         if(strcmp(arg->target,"-"))
  123.             set_mtime(arg->target, mtime);
  124.         return GOT_ONE;
  125.     } else {
  126.         fprintf(stderr,"%s\n", errmsg);
  127.         return MISSED_ONE;
  128.     }
  129. }
  130.  
  131. static  int dos_read(Stream_t *Dir, StreamCache_t *sc, int entry)
  132. {
  133.     return read_file(Dir, sc, entry, 1);
  134. }
  135.  
  136.  
  137. static  int unix_read(char *name, StreamCache_t *sc)
  138. {
  139.     return read_file(0, sc, -1, 0);
  140. }
  141.  
  142.  
  143. /*
  144.  * Open the named file for read, create the cluster chain, return the
  145.  * directory structure or NULL on error.
  146.  */
  147. static struct directory *writeit(char *dosname,
  148.                  char *longname,
  149.                  void *arg0,
  150.                  struct directory *dir)
  151. {
  152.     Stream_t *Target;
  153.     long now;
  154.     int type, fat, ret;
  155.     long date;
  156.     unsigned long filesize, newsize;
  157.     Arg_t *arg = (Arg_t *) arg0;
  158.  
  159.     if (arg->sc.File->Class->get_data(arg->sc.File,
  160.                       & date, &filesize, &type, 0) < 0 ){
  161.         fprintf(stderr, "Can't stat source file\n");
  162.         return NULL;
  163.     }
  164.  
  165.     if (type){
  166.         if (arg->verbose)
  167.             fprintf(stderr, "\"%s\" is a directory\n", longname);
  168.         return NULL;
  169.     }
  170.  
  171.     if (!arg->single)
  172.         fprintf(stderr,"Copying %s\n", longname);
  173.     if(got_signal)
  174.         return NULL;
  175.  
  176.     /* will it fit? */
  177.     if (filesize > getfree(arg->targetFs)) {
  178.         fprintf(stderr,"Disk full\n");
  179.         return NULL;
  180.     }
  181.     
  182.     /* preserve mod time? */
  183.     if (arg->preserve)
  184.         now = date;
  185.     else
  186.         time(&now);
  187.  
  188.     mk_entry(dosname, 0x20, 0, 0, now, dir);
  189.     Target = open_file(COPY(arg->targetFs), dir);
  190.     if(!Target){
  191.         fprintf(stderr,"Could not open Target\n");
  192.         cleanup_and_exit(1);
  193.     }
  194.     if (arg->needfilter & arg->textmode)
  195.         Target = open_filter(Target);
  196.     ret = copyfile(arg->sc.File, Target);
  197.     GET_DATA(Target, 0, &newsize, 0, &fat);
  198.     FREE(&Target);
  199.     if(ret < 0 ){
  200.         fat_free(arg->targetFs, fat);
  201.         return NULL;
  202.     } else {
  203.         mk_entry(dosname, 0x20, fat, newsize, now, dir);
  204.         return dir;
  205.     }
  206. }
  207.  
  208.  
  209. static int write_file(Stream_t *Dir, StreamCache_t *sc, int entry,
  210.               int needfilter)
  211. /* write a messy dos file to another messy dos file */
  212. {
  213.     int result;
  214.     Arg_t * arg = (Arg_t *) (sc->arg);
  215.  
  216.     arg->needfilter = needfilter;
  217.     if (arg->targetDir == Dir){
  218.         arg->ch.ignore_entry = -1;
  219.         arg->ch.source = entry;
  220.     } else {
  221.         arg->ch.ignore_entry = -1;
  222.         arg->ch.source = -2;
  223.     }
  224.     result = mwrite_one(arg->targetDir, arg->targetFs,
  225.                 arg->progname, arg->target, 0,
  226.                 writeit, (void *)arg, &arg->ch);
  227.     if(result == 1)
  228.         return GOT_ONE;
  229.     else
  230.         return MISSED_ONE;
  231. }
  232.  
  233.  
  234. static int dos_write(Stream_t *Dir, StreamCache_t *sc, int entry)
  235. {
  236.     return write_file(Dir, sc, entry, 0);
  237. }
  238.  
  239. static int unix_write(char *name, StreamCache_t *sc)
  240. /* write a Unix file to a messy DOS fs */
  241. {
  242.     return write_file(0, sc, 0, 1);
  243. }
  244.  
  245.  
  246. void mcopy(int argc, char **argv, int mtype)
  247. {
  248.     Stream_t *SubDir,*Dir, *Fs;
  249.     int have_target;
  250.     Arg_t arg;
  251.     int c, oops, ret;
  252.     char filename[VBUFSIZE];
  253.     
  254.     struct stat stbuf;
  255.  
  256.     int interactive;
  257.  
  258.     arg.progname = argv[0];
  259.  
  260.     /* get command line options */
  261.  
  262.     init_clash_handling(& arg.ch);
  263.  
  264.     oops = interactive = 0;
  265.  
  266.  
  267.     /* get command line options */
  268.     arg.preserve = 0;
  269.     arg.nowarn = 0;
  270.     arg.textmode = 0;
  271.     arg.interactive = 0;
  272.     arg.verbose = 0;
  273.     arg.type = mtype;
  274.     while ((c = getopt(argc, argv, "itnmvorsamORSAM")) != EOF) {
  275.         switch (c) {
  276.             case 'i':
  277.                 arg.interactive = 1;
  278.                 break;
  279.             case 't':
  280.                 arg.textmode = 1;
  281.                 break;
  282.             case 'n':
  283.                 arg.nowarn = 1;
  284.                 break;
  285.             case 'm':
  286.                 arg.preserve = 1;
  287.                 break;
  288.             case 'v':    /* dummy option for mcopy */
  289.                 arg.verbose = 1;
  290.                 break;
  291.             case '?':
  292.                 oops = 1;
  293.                 break;
  294.             default:
  295.                 if(handle_clash_options(&arg.ch, c))
  296.                     oops=1;
  297.                 break;
  298.         }
  299.     }
  300.  
  301.     if (oops || (argc - optind) < 1) {
  302.         fprintf(stderr,
  303.             "Mtools version %s, dated %s\n", mversion, mdate);
  304.         fprintf(stderr,
  305.             "Usage: %s [-itnmvV] sourcefile targetfile\n", argv[0]);
  306.         fprintf(stderr,
  307.             "       %s [-itnmvV] sourcefile [sourcefiles...] targetdirectory\n", 
  308.             argv[0]);
  309.         cleanup_and_exit(1);
  310.     }
  311.  
  312.     /* only 1 file to copy... */
  313.     arg.single = SINGLE;
  314.     
  315.     init_sc(&arg.sc);        
  316.     arg.sc.arg = (void *) &arg;
  317.     arg.sc.openflags = O_RDONLY;
  318.  
  319.     arg.targetDir = NULL;
  320.     if(mtype){
  321.  
  322.         /* Mtype = copying to stdout */
  323.  
  324.         have_target = 0;
  325.         arg.target = "-";
  326.         arg.sc.outname = filename;
  327.         arg.single = 0;        
  328.         arg.sc.callback = dos_read;
  329.         arg.sc.unixcallback = unix_read;
  330.     } else if(argc - optind >= 2 && 
  331.           argv[argc-1][0] && argv[argc-1][1] == ':'){
  332.  
  333.         /* Copying to Dos */
  334.  
  335.         have_target = 1;
  336.         Dir = open_subdir(&arg.sc, argv[argc-1], O_RDWR, &Fs);
  337.         arg.targetFs = Fs;
  338.         if(!Dir){
  339.             fprintf(stderr,"Bad target\n");
  340.             cleanup_and_exit(1);
  341.         }
  342.         get_name(argv[argc-1], filename, arg.sc.mcwd);
  343.         SubDir = descend(Dir, Fs, filename, 0, 0);
  344.         if (!SubDir){
  345.             /* the last parameter is a file */
  346.             if ( argc - optind != 2 ){
  347.                 fprintf(stderr,
  348.                     "%s: Too many arguments, or destination directory omitted\n", argv[0]);
  349.                 cleanup_and_exit(1);
  350.             }
  351.             arg.targetDir = Dir;
  352.             arg.sc.outname = 0; /* toss away source name */
  353.             arg.target = filename; /* store near name given as
  354.                         * target */
  355.             arg.single = 1;
  356.         } else {
  357.             arg.targetDir = SubDir;
  358.             FREE(&Dir);
  359.             arg.sc.outname = arg.target = filename;
  360.             arg.single = 0;
  361.         }
  362.         arg.sc.callback = dos_write;
  363.         arg.sc.unixcallback = unix_write;
  364.     } else {
  365.  
  366.         /* Copying to Unix */
  367.  
  368.         have_target = 1;
  369.         if (argc - optind == 1){
  370.             /* one argument: copying to current directory */
  371.             arg.single = 0;
  372.             have_target = 0;
  373.             arg.target = arg.sc.outname = filename;
  374.         } else if (strcmp(argv[argc-1],"-") && 
  375.                !stat(argv[argc-1], &stbuf) &&
  376.                S_ISDIR(stbuf.st_mode)){
  377.             arg.target = (char *) safe_malloc(VBUFSIZE + 1 + 
  378.                               strlen(argv[argc-1]));
  379.             strcpy(arg.target, argv[argc-1]);
  380.             strcat(arg.target,"/");
  381.             arg.sc.outname = arg.target+strlen(arg.target);
  382.         } else if (argc - optind != 2) {
  383.             /* last argument is not a directory: we should only
  384.              * have one source file */
  385.             fprintf(stderr,
  386.                 "%s: Too many arguments or destination directory omitted\n", 
  387.                 argv[0]);
  388.             cleanup_and_exit(1);
  389.         } else {
  390.             arg.target = argv[argc-1];
  391.             arg.sc.outname = filename;
  392.         }
  393.  
  394.         arg.sc.callback = dos_read;
  395.         arg.sc.unixcallback = unix_read;
  396.     }
  397.  
  398.     arg.sc.lookupflags = ACCEPT_PLAIN | DO_OPEN | arg.single;
  399.     ret=main_loop(&arg.sc, argv[0], argv + optind, 
  400.               argc - optind - have_target);
  401.     FREE(&arg.targetDir);
  402.     finish_sc(&arg.sc);
  403.  
  404.     cleanup_and_exit(ret);
  405. }
  406.